#include "SampleWindow.h"

SampleWindow::SampleWindow()
 : mWaveForm(NULL), mPosition(0), mWidth(1)
{
}

SampleWindow::SampleWindow( const WaveForm* waveForm )
 : mWaveForm(waveForm), mPosition(0), mWidth(32)
{
}

SampleWindow::SampleWindow( const SampleWindow& other )
{
	copyFrom( other );
}

const SampleWindow& SampleWindow::operator=( const SampleWindow& other )
{
	copyFrom( other );
	return *this;
}

void SampleWindow::copyFrom( const SampleWindow& other )
{
	mWaveForm = other.getWaveForm();
	mPosition = other.getPosition();
	mWidth = other.getWidth();
	// listeners are not copied
}

void SampleWindow::setPosition( int position )
{
	if ( mPosition!=position )
	{
		mPosition = position;
		fireChangeEvent();
	}
}

void SampleWindow::setWidth( std::size_t width )
{
	if ( mWidth!=width )
	{
		mWidth = width;
		fireChangeEvent();
	}
}

void SampleWindow::getSamples( WaveForm::Samples& samples ) const
{
	samples.resize( getWidth() );
	if ( !mWaveForm )
	{
		for ( std::size_t i=0; i<getWidth(); ++i )
			samples[i] = 0;
	}
	else
	{	
		const WaveForm::Samples waveFormSamples = getWaveForm()->getSamples();
		std::size_t waveFormNumSamples = waveFormSamples.size();

		int start = getPosition();
		int end = start + getWidth();
		int posInWaveFormSamples;
		int posInSamples = 0;
		for ( posInWaveFormSamples=start; posInWaveFormSamples<end; posInWaveFormSamples++, posInSamples++ )
		{
			if ( posInWaveFormSamples>=0 && posInWaveFormSamples<static_cast<int>(waveFormNumSamples) )
				samples[posInSamples] = waveFormSamples[posInWaveFormSamples];
			else 
				samples[posInSamples] = 0;
		}
	}
}

void SampleWindow::getNormalizedSamples( WaveForm::NormalizedSamples& normalizedSamples ) const
{
	WaveForm::Samples samples;
	getSamples( samples );
	WaveForm::normalizeSamples( samples, normalizedSamples );
}

int SampleWindow::samplePositionToViewPosition( int samplePosition, int viewWidth ) const
{
	int relPos = samplePosition - getPosition();
	int x = (int)( (float)relPos * (float)viewWidth / (float)getWidth() );
	return x;
}


int SampleWindow::viewPositionToSamplePosition( int viewPosition, int viewWidth ) const
{
	float singleSampleWidth = (float)viewWidth / (float)getWidth();
	int x = int( (float)viewPosition / singleSampleWidth );
	x += getPosition();
	return x;
}

void SampleWindow::fireChangeEvent()
{
	for ( std::size_t i=0; i<mListeners.size(); ++i )
		mListeners[i]->sampleWindowChanged( this );
}	